package mbsl.commons.games;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Shell;

import mbsl.commons.Commons;
import mbsl.commons.base.CommentPanel;
import mbsl.commons.lib.Comment;
import mbsl.commons.lib.Game;
import mbsl.system.TextProvider;
import mbsl.ui.Tree;
import mbsl.ui.Tree.TreeNode;
import mbsl.ui.dialogs.Dialogs;
import mbsl.ui.interfaces.Listener;

public class GameViewController {
	private static TextProvider tp = Commons.tp.prefix("common.comments");

	public GameViewController(GameController pParent, Shell pWindow) {
		mDialog = new GameViewDialog(pWindow);
		mParent = pParent;
		
		mCommentPanel = mDialog.getCommentPanel();
		
		mCommentPanel.addSaveListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent pE) {
				if (mCommentPanel.getActiveComment().getTitle().trim().isEmpty()) {
					Dialogs.error(mDialog.getWindow(), tp.get("fillMessage"), tp.get("titleError"));
					return;
				}
				if (mCommentPanel.getActiveComment().getBody().trim().isEmpty()) {
					Dialogs.error(mDialog.getWindow(), tp.get("fillMessage"), tp.get("bodyError"));
					return;
				}
				
				if (mGame.getComments() == null)
					mGame.setComments(new ArrayList<Comment<Game>>());

				boolean isNew;
				Comment<Game> comment;

				if (mCommentPanel.isNewActive()) {
					mGame.getComments().add(new Comment<Game>());
					
					comment = mGame.getComments().get(mGame.getComments().size() - 1);
					isNew = true;
				} else {
					// The comments are added in reverse order
					comment = mGame.getComments().get(mGame.getComments().size() - 1 - mCommentPanel.getActiveCommentIndex());
					isNew = false;
				}

				comment.setBody(mCommentPanel.getActiveComment().getBody());
				comment.setName(mCommentPanel.getActiveComment().getTitle());
				
				mParent.getCore().getDatabase().save(mGame);
				
				if (isNew) {
					mCommentPanel.getActiveComment().setBody(null);
					mCommentPanel.getActiveComment().setTitle(null);
					
					addComment(comment);
				}
			}
		});
		mCommentPanel.addDeleteListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent pE) {
				Comment<Game> comment = mGame.getComments().get(mGame.getComments().size() - 1 - mCommentPanel.getActiveCommentIndex());
				
				mGame.getComments().remove(comment);
				
				mParent.getCore().getDatabase().delete(comment);
				mParent.getCore().getDatabase().save(mGame);
				
				mCommentPanel.removeComment(mCommentPanel.getActiveCommentIndex());
			}
		});
		mDialog.getRating().addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent pE) {
				mGame.setRating(mDialog.getRating().getValue());
				
				mParent.getCore().getDatabase().save(mGame);
				
				if (mListeners != null)
					for (Listener listener : mListeners)
						listener.alert();
			}
		});
	}

	public void setGame(Game pGame) {
		if (pGame == mGame)
			return;
		
		mGame = pGame;
		
		mDialog.setTitle(mGame.getName());
		
		if (mGame.getGenre() != null)
			mDialog.setGenre(mGame.getGenre().getName());
		if (mGame.getLocation() != null)
			mDialog.setLocation(mGame.getLocation().getName());
		if (mGame.getMobyScore() != null)
			mDialog.setMobyScore(mGame.getMobyScore());
		else
			mDialog.setMobyScore(0);
		if (mGame.getRating() >= 0)
			mDialog.setRating(mGame.getRating());
		else
			mDialog.setRating(0);

		mDialog.setYear(mGame.getYear());
		
		mCommentPanel.clear();
		
		if (mGame.getComments() != null)
			for (Comment<Game> comment : mGame.getComments())
				addComment(comment);
		
		Tree tree = mDialog.getTree();
		
		tree.clear();
		
		if (mGame.getParent() != null || !mGame.getChildren().isEmpty())
			buildTree(tree);
	}
	private void buildTree(Tree pTree) {
		Game root = mGame;
		
		// Let's find the root of this tree
		while (root.getParent() != null)
			root = root.getParent();
		
		TreeNode node = pTree.new TreeNode();
		
		node.setData(root);
	
		buildSubTree(pTree, node);
	}
	private void buildSubTree(Tree pTree, TreeNode pNode) {
		// Effectively a DFS for building the set of TreeNodes.
		for (Game child : ((Game)pNode.getData()).getChildren()) {
			TreeNode childNode = pTree.new TreeNode(pNode);
			
			childNode.setData(child);
			
			buildSubTree(pTree, childNode);
		}
	}
	public Game getGame() {
		return mGame;
	}
	private void addComment(Comment<Game> pComment) {
		mCommentPanel.addComment(pComment.getName(), String.format("%1$tY-%1$tm-%1$td", pComment.getPosted()), pComment.getBody());
	}
	public void open() {
		mDialog.open();
	}
	public void addChangeListener(Listener pListener) {
		if (mListeners == null)
			mListeners = new ArrayList<Listener>();
		
		mListeners.add(pListener);
	}

	private List<Listener> mListeners;
	private Game mGame;
	private CommentPanel mCommentPanel;
	private GameViewDialog mDialog;
	private GameController mParent;
}
